package com.weilele.delegate

import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import com.weilele.mvvm.base.livedata.appCompatActivity
import com.weilele.mvvm.utils.safeGet
import java.lang.IllegalArgumentException
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

inline fun <reified T : ViewModel> mvvmViewModel(
    factory: ViewModelProvider.Factory? = null,
    noinline ownerCall: (() -> ViewModelStoreOwner?)? = null
) =
    ViewModelDelegate(T::class.java, factory, ownerCall)

inline fun <reified T : ViewModel> mvvmActivityViewModel(factory: ViewModelProvider.Factory? = null) =
    ActivityViewModelDelegate(T::class.java, factory)

class ViewModelDelegate<T : ViewModel>(
    private val cls: Class<T>,
    private val factory: ViewModelProvider.Factory? = null,
    private val ownerCall: (() -> ViewModelStoreOwner?)? = null/*指定在哪里创建*/
) :
    ReadOnlyProperty<Any?, T> {
    private var viewModelTemp: T? = null
    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        val viewModel = viewModelTemp
        return if (viewModel == null) {
            val viewModelStoreOwner = ownerCall?.invoke() ?: thisRef.safeGet<ViewModelStoreOwner>()
            ?: throw IllegalArgumentException("需要传入一个ViewModelStoreOwner类型的参数，或者在ViewModelStoreOwner的作用域类创建变量")
            val createViewModel = getViewModelProvider(viewModelStoreOwner, factory).get(cls)
            viewModelTemp = createViewModel
            createViewModel
        } else {
            viewModel
        }
    }
}

class ActivityViewModelDelegate<T : ViewModel>(
    private val cls: Class<T>,
    private val factory: ViewModelProvider.Factory? = null
) :
    ReadOnlyProperty<Fragment, T> {
    private var viewModelTemp: T? = null
    override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        val viewModel = viewModelTemp
        return if (viewModel == null) {
            val createViewModel =
                getViewModelProvider(thisRef.appCompatActivity!!, factory).get(cls)
            viewModelTemp = createViewModel
            createViewModel
        } else {
            viewModel
        }
    }
}

fun getViewModelProvider(
    owner: ViewModelStoreOwner,
    factory: ViewModelProvider.Factory?
): ViewModelProvider {
    return if (factory == null) {
        ViewModelProvider(owner)
    } else {
        ViewModelProvider(owner, factory)
    }
}